from PySide6.QtCore import Slot, Signal, QAbstractListModel, Qt, Property, QModelIndex
from PySide6.QtQml import QmlElement

from src.library.model import MusicMeta
from src.utils.common import format_duration

QML_IMPORT_NAME = "Backend"
QML_IMPORT_MAJOR_VERSION = 1


@QmlElement
class MusicListModel(QAbstractListModel):
    NameRole = Qt.ItemDataRole.UserRole
    ArtistsRole = Qt.ItemDataRole.UserRole + 1
    AlbumRole = Qt.ItemDataRole.UserRole + 2
    DurationRole = Qt.ItemDataRole.UserRole + 3
    AlbumUrlRole = Qt.ItemDataRole.UserRole + 4
    countChanged = Signal()

    def __init__(self, musics: [MusicMeta]):
        super().__init__()
        self._musics = musics

    @property
    def musics(self):
        return self._musics

    @Property(int, notify=countChanged)
    def count(self):
        return len(self._musics)

    @Slot(int, result=dict)
    def get(self, index):
        return self._musics[index].to_dict()

    def reset(self, musics: [MusicMeta]):
        self.beginResetModel()
        self._musics = musics
        self.endResetModel()
        self.countChanged.emit()

    def remove(self, index):
        self.beginRemoveRows(QModelIndex(), index, index)
        self._musics.pop(index)
        self.endRemoveRows()
        self.countChanged.emit()

    def extend(self, musics: [MusicMeta]):
        self.inserts(len(self._musics), musics)

    def append(self, music: MusicMeta):
        self.inserts(len(self._musics), [music])

    def inserts(self, index: int, musics: [MusicMeta]):
        self.beginInsertRows(QModelIndex(), index, index + len(musics) - 1)
        self._musics[index:index] = musics
        self.endInsertRows()
        self.countChanged.emit()

    def insert(self, index, music: MusicMeta):
        self.inserts(index, [music])

    def rowCount(self, parent=...):
        return len(self._musics)

    def data(self, index, role=...):
        if not index.isValid():
            return None
        if role == MusicListModel.NameRole:
            return self._musics[index.row()].name
        elif role == MusicListModel.ArtistsRole:
            return self._musics[index.row()].artists
        elif role == MusicListModel.AlbumRole:
            return self._musics[index.row()].album
        elif role == MusicListModel.DurationRole:
            temp = self._musics[index.row()].duration
            return format_duration(temp)
        elif role == MusicListModel.AlbumUrlRole:
            return self._musics[index.row()].album_pic
        return None

    def roleNames(self):
        return {
            MusicListModel.NameRole: b"name",
            MusicListModel.ArtistsRole: b"artists",
            MusicListModel.AlbumRole: b"album",
            MusicListModel.DurationRole: b"duration",
            MusicListModel.AlbumUrlRole: b"albumPic",
        }
